主要練習React官網中的題目,使用React達成做出圈圈叉叉的小遊戲,練習項目為
主要建立三個Components : Game,Board,Square
Components Tree :
Game :
import React from "react"
import Board from "./Board"
class Game extends React.Component
{
render()
{
return(
<Board />
)
}
}
ReactDOM.render(<Game />,document.getElementById("root"));
Board :
import React from "react"
import Square from "./Square"
class Board extends React.Component
{
render()
{
return(
<Square />
)
}
}
export default Board;
Square :
import React from "react"
class Square extends React.Component
{
render()
{
return(
<div> Square Component </div>
)
}
}
export default Square;
在Board中利用props將數據傳遞給Square後將他選染出來
Board :
class Board extends React.Component
{
renderSquare(i) {
return <Square value={i} />;
}
render()
{
const status = 'Next player: X';
return(
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)} //將數字裡用props傳遞給Square
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
)
}
}
Square :
class Square extends React.Component
{
render()
{
return(
<button className="square">
{this.props.value} //接收父層(Board)所傳遞的數字
</button>
)
}
}
結果 :
當點擊 Square component 時,能在方格中填入一個 X。
Square :
1.在Square中建立一個state以初始化Square Vaule中的值
2.建立一個function,當被點擊時觸發改變state中的值("" -> "X")
class Square extends React.Component
{
//Step1 : 建立constructor以初始化state中的Value
constructor(props)
{
super(props);
this.state = {
value:""
}
}
//Step2 : 建立一個function當點擊時觸發
handleClick = (e) => {
this.setState({
value : "X" //利用setState改變State中的值
});
}
render()
{
return(
<button className="square" onClick={this.handleClick}> //點擊時觸發
{this.state.value}
</button>
)
}
}
為了一次性的紀錄這九個方格中的值,所以需要將state提升到父層(Board)。
Board :
1.將state提升到父層(Board)
2.在父層建立當Square被點擊時觸發的function
3.將State的Value與handleClick function藉由props傳遞給Square
class Board extends React.Component
{
//Step1 : 將state提升到Board
constructor(props)
{
super(props);
this.state = {
squares : Array(9).fill("") //建立大小為9的陣列並填入""
};
}
//Step2 :建立當Square被點擊時觸發的function
handleClick = (i) => {
const squares = this.state.squares.slice();
squares[i] = 'X';
this.setState({squares: squares});
}
renderSquare(i) {
//Step3 :利用props傳遞給子層(Square)
return <Square value={this.state.squares[i]} onClick={() => this.handleClick(i)}/>;
}
render()
{
const status = 'Next player: X';
return(
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
)
}
}
Square :
1.移除自身state
2.將this.state更改為this.props(參數由父層傳遞)
class Square extends React.Component
{
//Step1 : 移除自身state
render()
{
return(
//Step2 : 將this.state更改為this.props(參數由父層傳遞)
<button className="square" onClick={() => this.props.onClick()}>
{this.props.value}
</button>
)
}
}
結果 :
會將第一步的預設值設定為"X",並設定一個boolean來判斷由"X"改為"O"以達到輪流的功能。
Board :
1.新增一個boolean xIsNext 來判斷符號的輪流
2.在handleClick function中建立判斷式以判斷現在的符號的狀況(xIsNext true or false)
3.反轉xIsNext狀態
class Board extends React.Component
{
constructor(props)
{
super(props);
this.state = {
squares : Array(9).fill(""),
xIsNext : true //Step1 :新增一個boolean xIsNext
};
}
handleClick = (i) => {
const squares = this.state.squares.slice();
squares[i] = this.state.xIsNext?"X":"O"; //Step2 :判斷現在的符號的狀況
this.setState({
squares : squares,
xIsNext : !this.state.xIsNext //Step3 :反轉xIsNext狀態
});
}
renderSquare(i) {
return <Square value={this.state.squares[i]} onClick={() => this.handleClick(i)}/>;
}
render()
{
const status = 'Next player: X';
return(
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
)
}
}
結果 :
建立一個function已檢測哪一方勝利,並在建立一個funciton再分出勝負後清除表格中的符號。
function calculateWinner :
export const calculateWinner = (squares) => {
//Step 1:建立一個九個勝利條件的Array
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++)
{
const [a, b, c] = lines[i];
//Step 2:檢測輸入的參數是否有達成獲勝條件
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c])
{
return squares[a]; //輸出獲勝的符號
}
}
return null;
}
Board :
1.建立一個參數(Winner)用來存取function calculateWinner計算的結果
2.利用Winner來判斷是否達成獲勝條件
3.新增一個按鈕用來重新開始
4.新增當重新開始按鈕被點擊後觸發的function
import {calculateWinner} from "./calculateWinner" //include function
class Board extends React.Component
{
constructor(props)
{
super(props);
this.state = {
squares : Array(9).fill(""),
xIsNext : true
};
}
handleClick = (i) => {
const squares = this.state.squares.slice();
squares[i] = this.state.xIsNext?"X":"O";
this.setState({
squares : squares,
xIsNext : !this.state.xIsNext
});
}
renderSquare(i) {
return <Square value={this.state.squares[i]} onClick={() => this.handleClick(i)}/>;
}
//Step 4:當重新開始按鈕被點擊後觸發的function
Reset = () => {
const emply = this.state.squares.fill("");
this.setState({
squares : emply,
xIsNext : true
});
}
render()
{
//Step 1:建立一個參數(Winner)用來存取function calculateWinner計算的結果
const Winner = calculateWinner(this.state.squares);
let status;
//Step 2:判斷是否達成獲勝條件
if(Winner)
{
status = "Winner :" + Winner;
alert(status);
}
else
{
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}
return(
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
<dic>
//Step 3:新增一個按鈕用來重新開始
<button onClick={this.Reset}>ReStart</button>
</dic>
</div>
)
}
}
結果:
參考資料 :
React學習指南